<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
    <!--  日志管理 -->
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 引入 Element UI 样式文件 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui@2.15.6/lib/theme-chalk/index.css">
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <!-- 引入 Element UI 脚本文件 -->
    <script src="https://cdn.jsdelivr.net/npm/element-ui@2.15.6/lib/index.js"></script>
    <!-- 引入 axios -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <!-- 引入 导航栏css 需要通过服务器请求-->
    <link rel="stylesheet" href="/css/nav.css" />
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        .sea {
            margin: 20px 25px 0px 22px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        body::-webkit-scrollbar {
            /* 隐藏滚动条 */
            display: none;
            /* Chrome, Safari, and Opera */
        }

        /*分页*/
        .block {
            padding: 10px;
            background: #fff;
            border: none;
            text-align: right;
            width: 100%;
            height: 30px;
            z-index: 2;
            position: fixed;
            bottom: 0;
            right: 0;
            box-shadow: 0px 0px 10px 1px #a0a0a0;
        }

        /* 表格数据列 */
        .ellipsis-text {
            white-space: nowrap;
            /* 不换行 */
            overflow: hidden;
            text-overflow: ellipsis;
            /* 显示省略号 */
        }
        .el-dialog__header{ /* 弹窗头部 */
            padding: 20px 20px 0;
        }
        .el-dialog--center .el-dialog__body{ 
            padding: 0px 25px 30px;
        }
        .el-divider--horizontal{ /* 水平分割线 */
            margin: 12px 0  ;
        }
        .el-divider{
            background-color: #ea8682;
        }
    </style>
</head>

<body>
    <div id="app">
        <div th:replace="nav :: nav"></div>
        <!-- 水印层 -->
        <div class="watermark">{{userNowName}} {{user}}</div>
        <div v-loading="loading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading"
            element-loading-background="rgba(0, 0, 0, 0.8)">
            <div style="margin-top: 70px;"></div>
            <div class="sea">
                <!--     面包屑导航 -->
                <div>
                    <el-breadcrumb separator-class="el-icon-arrow-right">
                        <el-breadcrumb-item><a th:href="@{/}">首页</a></el-breadcrumb-item>
                        <el-breadcrumb-item>后台管理</el-breadcrumb-item>
                        <el-breadcrumb-item>日志管理</el-breadcrumb-item>
                    </el-breadcrumb>
                </div>
                <!-- 搜索-->
                <div class="select" style="display: flex;">
                    <div>
                        <el-input placeholder="请输入操作者" v-model="selectOperator" class="input-with-select" size="mini" clearable></el-input>
                    </div>
                    <div style=" margin: 0 20px">
                        <el-select v-model="selectLogType" placeholder="请选择日志类型" size="mini" clearable >
                            <el-option  v-for="item in options"  :key="item.value"  :label="item.label" :value="item.value"> </el-option>
                        </el-select>
                    </div>
                    <div style=" margin: 0  20px 0 0">
                        <el-input placeholder="请输入请求接口" v-model="selectReqInterface" class="input-with-select" size="mini" clearable></el-input>
                    </div>
                    <el-button slot="append" size="mini" icon="el-icon-search" @click="searchList()">查询</el-button>
                </div>
                <!-- 重置 -->
                <div>
                    <el-row>
                        <el-button size="small" type="warning" icon="el-icon-refresh" @click="reload()">重置</el-button>
                    </el-row>
                </div>
            </div>
            <!-- stripe属性可以创建带斑马纹的表格； border表格边框 -->
            <el-table size="mini" :data="originalData" stripe style="width: 100%;  margin: 0 0 50px;">
                <!-- 操作者 -->
                <el-table-column prop="operator" label="操作者" align="center" width="150"></el-table-column>
                <!-- 日志类型 -->
                <el-table-column prop="logType" label="日志类型" align="center" width="110">
                    <template slot-scope="scope">
                        <el-tag size="mini" v-if="scope.row.logType" :type="getTagType(scope.row.logType)" disable-transitions>{{ scope.row.logType }}</el-tag>
                        <span v-else>--</span>
                    </template>
                </el-table-column>
                <!-- 记录时间 -->
                <el-table-column prop="recordTime" label="记录时间" sortable width="200" align="center">
                    <template slot-scope="scope">
                        <i class="el-icon-time"></i><span style="margin-left: 5px">{{ scope.row.recordTime }}</span>
                    </template>
                </el-table-column>
                <!-- 操作者IP -->
                <el-table-column prop="operatorIP" label="操作者IP" align="center" width="120"></el-table-column>
                <!-- 请求类型 -->
                <el-table-column prop="requestType" label="请求类型" align="center" width="130">
                    <template slot-scope="scope">
                        {{ scope.row.requestType | toUpperCase }}
                    </template>
                </el-table-column>
                <!-- 请求接口 -->
                <el-table-column label="请求接口" align="left" width="140">
                    <template slot-scope="scope">                       
                        <el-tooltip v-if="scope.row.requestInterface" class="item" effect="dark" :content="scope.row.requestInterface" placement="top"  :hide-after=2000>
                            <div class="ellipsis-text">{{ scope.row.requestInterface }}</div>
                        </el-tooltip>
                        <span v-else>--</span>
                    </template>
                </el-table-column>
                <!-- 响应媒体类型 -->
                <el-table-column prop="responseType" label="响应媒体类型" align="center" width="280"></el-table-column>
                <!-- 请求参数 -->
                <el-table-column prop="requestParameters" label="请求参数" align="left" width="250">
                    <template slot-scope="scope">
                        <el-tooltip v-if="scope.row.requestParameters" class="item" effect="dark" :content="scope.row.requestParameters" placement="top" :hide-after=2000>
                            <div class="ellipsis-text">{{ scope.row.requestParameters }}</div>
                        </el-tooltip>
                        <span v-else>--</span>
                    </template>
                </el-table-column>
                <!-- 操作 -->
                <el-table-column label="操作" align="center">
                    <template slot-scope="scope">
                        <el-link type="danger" style="font-size: 10px;"
                            @click="Detail(scope.$index, scope.row);">查看详情</el-link>
                    </template>
                </el-table-column>
            </el-table>
            <!-- 分页 -->
            <div class="block">
                <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
                    :current-page="pageNum" :page-sizes="[15,30,50,100,200]" :page-size="pageSize"
                    layout="total, sizes, prev, pager, next, jumper" :total="total"></el-pagination>
            </div>
            <!-- 查看详情 -->
            <el-dialog title="日志详情" center :visible.sync="dialogVisible" width="70%" >
                <el-divider style="background-color: aqua;"></el-divider>
                <el-descriptions  direction="vertical" :column="5" border>
                    <el-descriptions-item label="IP">{{detailData.operatorIP}}</el-descriptions-item>
                    <el-descriptions-item label="记录时间">{{detailData.recordTime}}</el-descriptions-item>
                    <el-descriptions-item label="Method">{{detailData.requestType}}</el-descriptions-item>
                    <el-descriptions-item label="API" :span="2">{{detailData.requestInterface}}</el-descriptions-item>
                </el-descriptions>
                <!-- 折叠面板 -->
                <el-collapse  >
                    <el-collapse-item title="请求参数" name="1">
                     <div v-if="detailData.requestParameters">{{detailData.requestParameters}}</div>
                     <div v-else>--</div>
                    </el-collapse-item>
                    <el-collapse-item title="响应媒体类型" name="2">
                     <div v-if="detailData.responseType">{{detailData.responseType}}</div>
                     <div v-else>--</div>
                    </el-collapse-item>
                    <el-collapse-item title="响应参数" name="3">
                     <div v-if="detailData.resdata !== '' ">{{detailData.resdata}}</div>
                     <div v-else>--</div>
                    </el-collapse-item>
                    <el-collapse-item title="错误内容" name="4">
                     <div v-if="detailData.error !== '' ">{{detailData.error}}</div>
                     <div v-else>--</div>
                    </el-collapse-item>
                </el-collapse>           
            </el-dialog>
        </div>
    </div>
</body>
<script>
    new Vue({
        el: '#app',
        data: {
            user: JSON.parse(localStorage.getItem("user")),
            userRole1: '',//	administrator的权限,boolen
            userRole2: '',//  user的   boolen
            userNowdata: '', // 当前用户的所有数据
            activeIndex: '4-2',
            userNowName: '',//当前用户姓名

            loading: true, //加载动画
            originalData: [], // 当前页面数据
            total: 0, //总条数
            pageNum: 1, //第几页
            pageSize: 15, //每页几条数据  

            options: [{ // 日志类型
                value: '登录日志',
                label: '登录日志'
            }, {
                value: '操作日志',
                label: '操作日志'
            }, {
                value: '错误日志',
                label: '错误日志'
            }, {
                value: '登录失败',
                label: '登录失败'
            }],
            operator:'',
            logType:'',
            requestInterface:'',
            selectOperator:'',//查询操作者
            selectLogType:'',//查询日志类型
            selectReqInterface: '',//查询请求接口
            dialogVisible: false,// 默认详情不显示
            detailData: {}, // 单行响应数据
     
            logData: {// 日志信息 (公用)
                operator: '',
                logType: '',
                recordTime: '',
                operatorIP: "192.168.2.21",
                requestType: '',
                requestInterface: '',
                requestParameters: '',
                responseType: '',
                resdata:'',
                error:''
            },

        },
        created() {
            this.getUserRole(); // 加载用户权限
            // 模拟加载动画
            setTimeout(() => {
                this.loading = false;
            }, 500); // 1秒后执行
        },
        methods: {
            // 账号退出(通用）
            logoutButton() {
                axios.get("/user/logout")
            },
            // 用户权限（通用）
            getUserRole() {
                axios.get("/user/now?username=" + this.user)
                    .then(res => {
                        this.userRole1 = (res.data.UserNowdata[0].role === 'administrator')
                        this.userRole2 = (res.data.UserNowdata[0].role === 'user')
                        this.userNowdata = res.data.UserNowdata
                        this.userNowName = this.userNowdata[0].z_name;
                        this.getLogList();
                        // 访问请求的相关信息,写进日志
                        this.getLog(res);
                        axios.post('/log', {  ...this.logData, logType: '操作日志'} )
                    });
            },
            // 重置页面
            reload() {
                window.location.reload()
            },
            // 分页
            handleSizeChange(val) {
                this.pageSize = val;
                console.log(`每页 ${this.pageSize} 条`);
                this.getLogList();
            },
            handleCurrentChange(val) {
                this.pageNum = val;
                console.log(`当前页: ${val}`);
                this.getLogList();
            },
            // 请求 日志 分页数据
            getLogList() {
              axios.get("/log/page?pageNum=" + this.pageNum + "&pageSize=" + this.pageSize + "&operator=" + this.operator + "&logType=" + this.logType + "&requestInterface=" + this.requestInterface)       
                .then(res => {
                        this.originalData = res.data.logData;
                        this.total = res.data.total;
                        // 访问请求的相关信息,写进日志
                        this.getLog(res);
                        axios.post('/log', {  ...this.logData, logType: '操作日志'} )
                    });
            },
            // 单个/组合搜索
            searchList() {
                this.pageNum = 1; //不先把页面等于1的话，有些会搜索不到
                this.operator = this.selectOperator
                this.logType = this.selectLogType
                this.requestInterface = this.selectReqInterface
                this.getLogList();
            },
            // 根据日志类型设置标签颜色
            getTagType(logType) {
                if (logType.includes('失败') || logType.includes('错误')) {
                    return 'danger';
                } else if (logType.includes('登录日志')) {
                    return 'warning';
                } 
                else {
                    return 'success';
                }          
            },
            // 查看详情
            Detail(index, row){
                this.detailData=row
                this.dialogVisible = true;
            },
            // 从接口的res 获取日志 (公用）
            getLog(res) {
                this.logData.operator = this.user, // 操作者
                this.logData.recordTime = new Date().toLocaleString(), // 记录时间
                // this.logData.operatorIP = 操作者ip
                this.logData.requestType = res.config.method; // 请求类型
                this.logData.requestInterface = '/api' + res.config.url;// 请求URL
                this.logData.requestParameters = res.config.data; // 请求参数
                this.logData.responseType = res.headers['content-type'];// 实体主体的媒体类型
                if(res.data){ // 响应参数
                    this.logData.resdata = JSON.stringify(res.data).substring(0, 5000);// 数组转成字符串，最大写入量5000
                    this.logData.error=''
                }else{ // 错误信息
                    this.logData.resdata =''
                   this.logData.error =  JSON.stringify(res).substring(0, 5000)
                }
            },
        },
        // 改成大写
        filters: {
            toUpperCase(value) {
                return value.toUpperCase();
            }
        }
    });
</script>